package cn.roadtrip.mtravelbusinessmodule.bs.active;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.roadtrip.mtravelbusinessmodule.bs.vpo.BsActiveItemVPO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.dto.CoupleShopPdtDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelactive.dto.BsActiveActiveItemTypeDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelactive.dto.BsActiveItemDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelactive.tables.records.BsActiveActiveitemtypeRecord;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelactive.tables.records.BsActiveItemRecord;
import cn.roadtrip.uredismodule.util.RedisUtil;
import cn.roadtrip.utilmodule.util.DataBean;
import cn.roadtrip.utilmodule.util.enumpck.Enum_ActiveItemType;
import cn.roadtrip.utilmodule.util.enumpck.Enum_TravelGroupTourOrderStats;
import com.github.yitter.idgen.YitIdHelper;
import com.google.gson.Gson;
import lombok.*;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;

import static cn.roadtrip.mtravelbusinessmodule.sql.couple.tables.CoupleShopPdt.COUPLE_SHOP_PDT;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelactive.Tables.BS_ACTIVE_ACTIVEITEMTYPE;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelactive.Tables.BS_ACTIVE_ITEM;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelgroup.Tables.BS_TRAVELGROUP_TOURORDERRECORD;

/**
 * 旅游活动操作
 */
@Component
public class TravelActiveImpl {

    @Autowired
    private DSLContext dslContext;

    @Autowired
    private RedisUtil redisUtil;


    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _TitleGroup_ {
        private String mainTitle;//主标题
        private String secondTitle;//副标题
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_createTravelActive {
        private java.util.List<String> typeCodes;//所属活动类别代码
        private Enum_ActiveItemType activeItemType;//活动类型
        private String itemId;//对象条目ID
        private String startDate;
        private String endDate;
        private Integer sortNum;//排序序号
        private String priceExpireTime;//活动价超时时间
        private String originPrice;//原价
        private String activePrice;//活动价
        private _TitleGroup_ titleGroup;//标题组
        private java.util.List<String> images;//图片数组
        private java.util.Map<String, Object> extInfors;//扩展信息
    }

    /**
     * 创建旅游活动
     *
     * @param model
     * @return
     */
    public DataBean createTravelActive(Model_createTravelActive model) {
        try {
            return dslContext.transactionResult(ctx -> {
                //添加活动条目
                String activeId = "" + YitIdHelper.nextId();
                Gson gson = new Gson();
                int count = dslContext.insertInto(BS_ACTIVE_ITEM)
                        .set(new BsActiveItemRecord(
                                activeId,
                                false,
                                model.getActiveItemType().getCode(),
                                model.getItemId(),
                                DateUtil.parseDate(model.getStartDate()).getTime(),
                                DateUtil.parseDate(model.getEndDate()).getTime(),
                                model.getSortNum(),
                                System.currentTimeMillis(),
                                DateUtil.parseDate(model.getPriceExpireTime()).getTime(),
                                System.currentTimeMillis(),
                                new BigDecimal(model.getOriginPrice()),
                                new BigDecimal(model.getActivePrice()),
                                gson.toJson(model.getTitleGroup()),
                                gson.toJson(model.getImages()),
                                model.getExtInfors() == null ? "{}" : gson.toJson(model.getExtInfors())
                        ))
                        .execute();
                if (count == 0)
                    throw new RuntimeException("添加活动条目失败");
                //添加关联
                for (String typeCode : model.getTypeCodes()) {
                    count = dslContext.insertInto(BS_ACTIVE_ACTIVEITEMTYPE)
                            .set(new BsActiveActiveitemtypeRecord(
                                    false,
                                    model.getActiveItemType().getCode(),
                                    activeId,
                                    typeCode,
                                    System.currentTimeMillis(),
                                    System.currentTimeMillis()
                            ))
                            .execute();
                    if (count == 0)
                        throw new RuntimeException("添加活动关联失败");
                }
                dslContext.commit();
                return DataBean.suc(true, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return DataBean.err("trans-err", e.getMessage());
        }
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_unbindTravelActive {
        String activeId;//活动ID
    }

    /**
     * 解除活动条目绑定
     *
     * @param model
     * @return
     */
    public DataBean unbindTravelActive(Model_unbindTravelActive model) {
        try {
            return dslContext.transactionResult(ctx -> {
                //删除条目
                int count = dslContext.update(BS_ACTIVE_ITEM)
                        .set(BS_ACTIVE_ITEM.TRASH, true)
                        .where(
                                BS_ACTIVE_ITEM.ID.eq(model.getActiveId())
                        ).execute();
                if (count == 0)
                    throw new RuntimeException("删除条目失败");
                //解除关联
                count = dslContext.update(BS_ACTIVE_ACTIVEITEMTYPE)
                        .set(BS_ACTIVE_ACTIVEITEMTYPE.TRASH, true)
                        .where(
                                BS_ACTIVE_ACTIVEITEMTYPE.ACTIVEITEMID.eq(model.getActiveId())
                        )
                        .and(BS_ACTIVE_ACTIVEITEMTYPE.TRASH.eq(false))
                        .execute();
                if (count == 0)
                    throw new RuntimeException("解除绑定失败");
                dslContext.commit();
                return DataBean.suc(true, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return DataBean.err("trans-err", e.getMessage());
        }
    }


    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_updateTravelActiveInfor {
        private String activeId;//活动ID
        private java.util.List<String> typeCodes;//所属活动类别代码
        private String startDate;
        private String endDate;
        private Integer sortNum;//排序序号
        private String priceExpireTime;//活动价超时时间
        private String originPrice;//原价
        private String activePrice;//活动价
        private _TitleGroup_ titleGroup;//标题组
        private java.util.List<String> images;//图片数组
        private java.util.Map<String, Object> extInfors;//扩展信息
    }

    /**
     * 修改活动信息
     *
     * @param model
     * @return
     */
    public DataBean updateTravelActiveInfor(Model_updateTravelActiveInfor model) {
        try {
            return dslContext.transactionResult(ctx -> {
                //获取活动条目
                BsActiveItemRecord record = dslContext.selectFrom(BS_ACTIVE_ITEM)
                        .where(
                                BS_ACTIVE_ITEM.ID.eq(model.getActiveId())
                        ).fetchOne();
                if (record == null) {
                    return DataBean.err("not-exist", "活动不存在");
                }
                //修改活动条目
                Gson gson = new Gson();
                record.setStartdate(DateUtil.parseDate(model.getStartDate()).getTime());
                record.setEnddate(DateUtil.parseDate(model.getEndDate()).getTime());
                record.setSortnum(model.getSortNum());

                record.setPriceexpiretime(DateUtil.parseDate(model.getPriceExpireTime()).getTime());
                record.setModifytime(System.currentTimeMillis());
                record.setOriginprice(new BigDecimal(model.getOriginPrice()));
                record.setActiveprice(new BigDecimal(model.getActivePrice()));
                record.setTitlegroup(gson.toJson(model.getTitleGroup()));
                record.setImages(gson.toJson(model.getImages()));
                record.setExtinfors(model.getExtInfors() == null ? "{}" : gson.toJson(model.getExtInfors()));
                int count = dslContext.update(BS_ACTIVE_ITEM)
                        .set(record)
                        .execute();
                if (count == 0)
                    throw new RuntimeException("修改活动条目失败");
                //删除原有绑定记录
                count = dslContext.update(BS_ACTIVE_ACTIVEITEMTYPE)
                        .set(BS_ACTIVE_ACTIVEITEMTYPE.TRASH, true)
                        .set(BS_ACTIVE_ACTIVEITEMTYPE.MODIFYTIME, System.currentTimeMillis())
                        .where(
                                BS_ACTIVE_ACTIVEITEMTYPE.TRASH.eq(false)
                        ).and(
                                BS_ACTIVE_ACTIVEITEMTYPE.ACTIVEITEMID.eq(model.getActiveId())
                        ).execute();
                if (count == 0)
                    throw new RuntimeException("删除原有绑定记录失败");
                //新增绑定记录
                for (String typeCode : model.getTypeCodes()) {
                    count = dslContext.insertInto(BS_ACTIVE_ACTIVEITEMTYPE)
                            .set(new BsActiveActiveitemtypeRecord(
                                    false,
                                    record.getType(),
                                    model.getActiveId(),
                                    typeCode,
                                    System.currentTimeMillis(),
                                    System.currentTimeMillis()
                            ))
                            .execute();
                    if (count == 0)
                        throw new RuntimeException("添加活动关联失败");
                }
                dslContext.commit();
                return DataBean.suc(true, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return DataBean.err("trans-err", e.getMessage());
        }
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_getTravelActiveList {
        private Enum_ActiveItemType activeItemType;//活动类型
        private java.util.List<String> typeCodes;//可选
    }


    /**
     * 旅游团活动报名人数
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    private static class _SignUpTravelGroupPeopleNum_ {
        private String travelGroupId;
        private Integer peopleNum;
    }

    /**
     * 活动类型代码
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    private static class _ActiveItemTypeCode_ {
        private String travelGroupId;
        private String typeCode;
        private String city;
    }

    /**
     * 查询活动列表
     *
     * @param model
     * @return
     */
    public DataBean getTravelActiveList(Model_getTravelActiveList model) {
        try {
            java.util.List<BsActiveItemDTO> list = dslContext.selectFrom(BS_ACTIVE_ITEM)
                    .where(
                            model.getActiveItemType() == null ? DSL.noCondition() : BS_ACTIVE_ITEM.TYPE.eq(model.getActiveItemType().getCode())
                    )
                    .and(BS_ACTIVE_ITEM.TRASH.eq(false))
                    .and(
                            model.getTypeCodes() == null ? DSL.noCondition() : (
                                    BS_ACTIVE_ITEM.ID.in(
                                            dslContext.selectDistinct(BS_ACTIVE_ACTIVEITEMTYPE.ACTIVEITEMID)
                                                    .from(BS_ACTIVE_ACTIVEITEMTYPE)
                                                    .where(
                                                            BS_ACTIVE_ACTIVEITEMTYPE.TRASH.eq(false)
                                                    ).and(
                                                            model.getActiveItemType() == null ? DSL.noCondition() : BS_ACTIVE_ACTIVEITEMTYPE.ITEMTYPE.eq(model.getActiveItemType().getCode())
                                                    ).and(
                                                            model.getTypeCodes() == null ? DSL.noCondition() : BS_ACTIVE_ACTIVEITEMTYPE.TYPECODE.in(model.getTypeCodes())
                                                    )
                                    )
                            )
                    )
                    .and(BS_ACTIVE_ITEM.ENDDATE.ge(System.currentTimeMillis()))
                    .orderBy(BS_ACTIVE_ITEM.SORTNUM.asc())
                    .fetch().into(BsActiveItemDTO.class);
            if (list == null || list.isEmpty()) {
                return DataBean.sucEmpty();
            }
            java.util.List<String> travelIds = new ArrayList<>();
            java.util.List<String> producIds = new ArrayList<>();
            for (BsActiveItemDTO bsActiveItemDTO : list) {
                if (bsActiveItemDTO.getType().equals(Enum_ActiveItemType.TravelLine.getCode()))
                    travelIds.add(bsActiveItemDTO.getId());
                else {
                    producIds.add(bsActiveItemDTO.getId());
                }
            }
            java.util.Map<String, Object> rsmap = new HashMap<>();
            if (!travelIds.isEmpty()) {
                //查询抱团人数
                java.util.List<_SignUpTravelGroupPeopleNum_> signUpTravelGroupPeopleNums = dslContext.select(
                                BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID.as("travelGroupId"),
                                DSL.count(BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID).as("peopleNum")
                        ).from(
                                BS_TRAVELGROUP_TOURORDERRECORD
                        )
                        .where(
                                BS_TRAVELGROUP_TOURORDERRECORD.STATS.in(
                                        Enum_TravelGroupTourOrderStats.Finished.getCode(),
                                        Enum_TravelGroupTourOrderStats.Mark.getCode(),
                                        Enum_TravelGroupTourOrderStats.Payed.getCode(),
                                        Enum_TravelGroupTourOrderStats.Join.getCode()
                                )
                        )
                        .and(
                                BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID.in(
                                        travelIds
                                )
                        )
                        .groupBy(BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID)
                        .fetchInto(_SignUpTravelGroupPeopleNum_.class);
                //查询活动所有所属类型代码
                java.util.List<BsActiveActiveItemTypeDTO> typeCodes = dslContext.selectFrom(
                                BS_ACTIVE_ACTIVEITEMTYPE
                        ).where(
                                BS_ACTIVE_ACTIVEITEMTYPE.TRASH.eq(false)
                        )
                        .and(BS_ACTIVE_ACTIVEITEMTYPE.ACTIVEITEMID.in(travelIds))
                        .fetchInto(BsActiveActiveItemTypeDTO.class);
                java.util.Map<String, java.util.List<String>> typeCodeMap = new HashMap<>();
                for (BsActiveActiveItemTypeDTO dto : typeCodes) {
                    java.util.List<String> ls = typeCodeMap.get(dto.getActiveItemId());
                    if (ls == null) {
                        ls = new ArrayList<>();
                        typeCodeMap.put(dto.getActiveItemId(), ls);
                    }
                    ls.add(dto.getTypeCode());
                }
//汇总报名人数
                java.util.Map<String, Integer> signUpTravelGroupPeopleNumMap = new HashMap<>();
                for (_SignUpTravelGroupPeopleNum_ _SignUpTravelGroupPeopleNum_ : signUpTravelGroupPeopleNums) {
                    signUpTravelGroupPeopleNumMap.put(_SignUpTravelGroupPeopleNum_.getTravelGroupId(), _SignUpTravelGroupPeopleNum_.getPeopleNum());
                }
                //重新整理汇总列表
                java.util.List<BsActiveItemVPO> rsList = new ArrayList<>();
                Gson gson = new Gson();
                for (BsActiveItemDTO dto : list) {
                    try {
                        gson.fromJson(
                                dto.getImages(),
                                new com.google.gson.reflect.TypeToken<java.util.List<String>>() {
                                }.getType()
                        );
                    } catch (Exception e) {
                        dto.setImages("[]");
                    }
                    try {
                        gson.fromJson(
                                dto.getExtInfors(),
                                new com.google.gson.reflect.TypeToken<java.util.Map<String, Object>>() {
                                }.getType()
                        );
                    } catch (Exception e) {
                        dto.setExtInfors("{}");
                    }
                    rsList.add(new BsActiveItemVPO(
                            dto.getId(),
                            dto.getTrash(),
                            dto.getType(),
                            dto.getItemId(),
                            dto.getStartDate(),
                            dto.getEndDate(),
                            dto.getSortNum(),
                            dto.getCreateTime(),
                            dto.getPriceExpireTime(),
                            dto.getModifyTime(),
                            dto.getOriginPrice(),
                            dto.getActivePrice(),

                            gson.fromJson(
                                    dto.getTitleGroup(),
                                    BsActiveItemVPO._TitleGroup_.class
                            ),
                            gson.fromJson(
                                    dto.getImages(),
                                    new com.google.gson.reflect.TypeToken<java.util.List<String>>() {
                                    }.getType()
                            ),
                            gson.fromJson(
                                    dto.getExtInfors(),
                                    new com.google.gson.reflect.TypeToken<java.util.Map<String, Object>>() {
                                    }.getType()
                            ),
                            typeCodeMap.get(dto.getId()),
                            signUpTravelGroupPeopleNumMap.get(dto.getItemId())
                    ));
                }
                //读取活动类型
                java.util.Map<String, java.util.List<BsActiveItemVPO>> travel = new HashMap<>();
                try {
                    String typestr = redisUtil.get("TravelActiveType");//redis中读取活动类型
                    JSONArray jsonArray = new JSONArray(typestr);
                    if (jsonArray.size() == 0) {
                        return DataBean.err("type-null", "活动类型为空");
                    }
                    for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        String gtype = jsonObject.getStr("gtype");
                        JSONArray types = jsonObject.getJSONArray("typeCode");
                        for (int j = 0; j < types.size(); j++) {
                            JSONObject tjson = types.getJSONObject(j);
                            for (BsActiveItemVPO vpo : rsList) {
                                for (String typeCode : vpo.getTypeCodes()) {
                                    if (!(model.getTypeCodes() == null || model.getTypeCodes().isEmpty())) {
                                        if (!model.getTypeCodes().contains(tjson.getStr("code"))) {
                                            continue;
                                        }
                                    }
                                    if (tjson.getStr("code").equals(typeCode)) {
                                        java.util.List<BsActiveItemVPO> list1 = travel.get(gtype);
                                        if (list1 == null) {
                                            list1 = new ArrayList<>();
                                            travel.put(gtype, list1);
                                        }
                                        list1.add(vpo);
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return DataBean.err("err", e.getMessage());
                }
                rsmap.put("travel", travel);
            }
//查询产品
            if (!producIds.isEmpty()) {
                java.util.List<CoupleShopPdtDTO> plist = dslContext.selectFrom(COUPLE_SHOP_PDT)
                        .where(
                                COUPLE_SHOP_PDT.ID.in(producIds)
                        ).fetchInto(CoupleShopPdtDTO.class);
                rsmap.put("product", plist);
            }

            DataBean db = DataBean.suc(rsmap, 1, "suc", "操作成功");
            return db;
        } catch (Exception e) {
            e.printStackTrace();
            return DataBean.err("err", e.getMessage());
        }

    }
}
